package site.weiyikai.eventdriven.core;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import site.weiyikai.eventdriven.event.BaseCommanderEvent;
import site.weiyikai.eventdriven.properties.AsyEventDrivenProperties;

import javax.annotation.Resource;
import java.util.concurrent.*;


/**
 * 描述：异步推送事件（事件交付器）实现类
 *
 * @author 程序员小魏
 * 创建时间: 2023/11/06
 */
@Slf4j
public class AsynchronousDelivery implements Delivery, DisposableBean, InitializingBean {

    @Resource
    private AsyEventDrivenProperties asyProperties;

    private ExecutorService reportServiceExecutor;

    public AsynchronousDelivery() {
        super();
    }

    @Override
    public void afterPropertiesSet() {
        reportServiceExecutor = new ThreadPoolExecutor
                (asyProperties.getReportExecutorProperties().getCorePoolSize(),
                        asyProperties.getReportExecutorProperties().getMaximumPoolSize(),
                        asyProperties.getReportExecutorProperties().getKeepAliveTime(),
                        TimeUnit.MILLISECONDS,
                        new LinkedBlockingDeque<>(asyProperties.getReportExecutorProperties().getWorkQueueCapacity()),
                        new DaemonThreadFactory("reportServiceExecutor"),
                        new ThreadPoolExecutor.CallerRunsPolicy());
    }

    @Override
    @SneakyThrows
    public void destroy() {
        reportServiceExecutor.shutdown();
    }

    @Override
    public <T> void publishTo(Iterable<EventSubscriber<T>> subscribers, T event) {
        if (subscribers != null && (event instanceof BaseCommanderEvent)) {
            for (EventSubscriber<T> sub : subscribers) {
                reportServiceExecutor.submit(() -> {
                    try {
                        sub.onEvent(event);
                    } catch (Exception e) {
                        log.error("publishTo reportServiceExecutor thread occur error:", e);
                    }
                });
            }

        }
    }
}